Fix xtime_lock handling in timer interrupt. There's no need
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 16 Aug 2005 15:40:43 +0000 (15:40 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 16 Aug 2005 15:40:43 +0000 (15:40 +0000)
to hold it while doing local VCPU work, and there might be
danger of deadlock if we do.

Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c

index ea421f080b4d71b0f9d6ee703036f9639c9a326a..4ceded947a4d436d31a72a5c05084be7a03c00e6 100644 (file)
@@ -540,17 +540,14 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 #endif
 
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void do_timer_interrupt(int irq, void *dev_id,
-                                       struct pt_regs *regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        s64 delta, delta_cpu;
        int cpu = smp_processor_id();
        struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
 
+       write_seqlock(&xtime_lock);
+
        do {
                get_time_values_from_xen();
 
@@ -582,7 +579,18 @@ static inline void do_timer_interrupt(int irq, void *dev_id,
                do_timer(regs);
        }
 
-       /* Local CPU jiffy work. */
+       if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
+               update_wallclock();
+               clock_was_set();
+       }
+
+       write_sequnlock(&xtime_lock);
+
+       /*
+         * Local CPU jiffy work. No need to hold xtime_lock, and I'm not sure
+         * if there is risk of deadlock if we do (since update_process_times
+         * may do scheduler rebalancing work and thus acquire runqueue locks).
+         */
        while (delta_cpu >= NS_PER_TICK) {
                delta_cpu -= NS_PER_TICK;
                per_cpu(processed_system_time, cpu) += NS_PER_TICK;
@@ -590,29 +598,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id,
                profile_tick(CPU_PROFILING, regs);
        }
 
-       if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
-               update_wallclock();
-               clock_was_set();
-       }
-}
-
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       /*
-        * Here we are in the timer irq handler. We just have irqs locally
-        * disabled but we don't know if the timer_bh is running on the other
-        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-        * the irq version of write_lock because as just said we have irq
-        * locally disabled. -arca
-        */
-       write_seqlock(&xtime_lock);
-       do_timer_interrupt(irq, NULL, regs);
-       write_sequnlock(&xtime_lock);
        return IRQ_HANDLED;
 }